home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
OPXMS114.ARJ
/
OPXMS.DOC
< prev
next >
Wrap
Text File
|
1992-07-29
|
16KB
|
408 lines
OPXMS.DOC
TurboPower Software
July 1992
Of the three modules in Object Professional that provide memory management
(OPEMS, OPEXTMEM, and OPXMS), OPXMS is often the best choice because of its
many special features. These features include the ability to lock blocks of
memory, use the High Memory Area, take advantage of Upper Memory Blocks, and
associate handles with blocks of memory.
Locking allocated extended memory blocks assures that they will not be moved
by the XMS memory manager. OPXMS includes functions to lock and unlock blocks
of extended memory, and to get information about the memory blocks.
The High Memory Area (HMA) is a 64KB region of memory that Microsoft
"discovered" when they were developing Windows/286. It was given this special
name because it exists in the extended memory, but unlike the rest of extended
memory, it can be directly accessed without being in protected mode. This is
accomplished by enabling the CPU's A20 line, which allows the generation of
21-bit physical addresses. OPXMS includes functions that allow you to enable,
disable, and query the state of the A20 line. RequestHMA and ReleaseHMA allow
you to allocate and deallocate memory in the HMA.
Some XMS memory managers support functions to allocate and free Upper Memory
Blocks (UMBs). UMBs are areas of memory located above the 640K of DOS
accessible memory and below the 1 megabyte boundary. This memory is generally
only accessible under '386 extended memory managers. OPXMS contains functions
to allocate and free UMBs.
OPXMS also contains functions that determine whether XMS memory is installed
and, if so, how much is currently available. You can allocate/deallocate and
access blocks of extended memory by taking the following steps:
1. Find out how much extended memory is available by calling QueryFreeExtMem.
2. If the available memory is sufficient, use AllocateExtMem to allocate the
required amount.
3. Once the memory is allocated, use MoveExtMemBlock to move data from normal
RAM to extended memory and back again.
4. To dispose of a block of extended memory, call FreeExtMem.
AllocateExtMem allows you to allocate memory only in 1K blocks (1,024 bytes).
This makes extended memory less convenient to use for general purpose storage,
but it also means that you can allocate several megabytes of contiguous memory
with a single call to AllocateExtMem.
Another important memory management issue is that the MoveExtMemBlock
function, which is used to transfer data between normal and extended memory,
does not allow you to move data in bytes, only in words (two bytes). This
means that you must be especially careful when defining your data structures,
and that you will sometimes need to pad data structures with dummy bytes to
ensure that their sizes are even numbers. The one benefit of this restriction
is that you can move up to 128K of contiguous data with a single call to
MoveExtMem.
Reference Section
-----------------
Types
ExtMemPtr =
record
case Boolean of
False : (RealPtr : Pointer);
True : (ProtectedPtr : LongInt);
end;
A data structure used to specify pointers to either conventional or extended
memory. In conventional memory, pointers are normal Segment:Offset pointers.
In protected memory, linear addresses (longints) are used. This type is used
only for the MoveExtMemBlock and LockExtMemBlock functions.
Variables
XmsControl : Pointer;
Stores a pointer to the XMS control function. This is intended primarily
for internal use.
Error Codes
The following lists all error codes that can be returned from the XMS
functions:
$00 Success
$80 Function not implemented
$81 VDISK device driver was detected
$82 A20 error occurred
$8E General driver error
$8F Unrecoverable driver error
$90 High memory area does not exist
$91 High memory area already in use
$92 Size requested is less than /HMAMIN=parameter
$93 High memory area not allocated
$94 A20 line is still enabled
$A0 All extended memory is allocated
$A1 Extended memory handles exhausted
$A2 Invalid handle
$A3 Invalid source handle
$A4 Invalid source offset
$A5 Invalid destination handle
$A6 Invalid destination offset
$A7 Invalid length
$A8 Invalid overlap in move request
$A9 Parity error detected
$AA Block is not locked
$AB Block is locked
$AC Lock count overflowed
$AD Lock failed
$B0 Smaller UMB is available
$B1 No UMBs are available
$B2 Invalid UMB segment number
Declaration
function AllocateExtMem(SizeInK : Word; var XmsHandle : Word) : Byte;
Purpose
Allocate a block of extended memory.
Description
This function allocates a block of extended memory SizeInK kilobytes in
size, and returns the XMS handle in XMSHandle. A status code is returned
in the function result.
Example
var
Handle : Word;
Res : Byte;
begin
Res := AllocateExtMem(256, Handle);
if Res <> 0 then
WriteLn('Cannot allocate XMS memory. Result: ' Res);
end;
Tries to allocate 256k of extended memory and prints the error code if not
successful.
See Also
FreeExtMem
Declaration
function AllocUpperMemBlock(SizeInParas : Word; var SegmentBase : Word;
var Size : Word) : Byte;
Purpose
Allocate an upper memory block (UMB).
Description
If this function succeeds, SegmentBase contains the segment of the allocated
upper memory block and Size contains the size (in kilobytes) of the block. If
insufficient memory is available for the requested upper memory block, then
the size of the largest free upper memory block is returned in Size.
Upper memory blocks are paragraph aligned (the offset is always 0). By
definition, UMBs are located below the 1 megabyte address boundary, therefore
there is no need to enable the A20 line to access the memory in a UMB. There
are no restrictions on using this memory in DOS calls or pointing ISRs into
this memory.
This function is not implemented by most '286 XMS drivers. It is implemented
by most '386 memory managers such as QEMM, 386MAX, and EMM386.
See also
FreeUpperMemBlock
Declaration
function FreeExtMem(XmsHandle : Word) : Byte;
Purpose
Free a block of extended memory.
Description
XMSHandle is the XMS handle returned by the previous call to AllocateExtMem.
Note that this function must be called to free any allocated blocks of
extended memory before a program terminates (it is not done automatically).
Otherwise, they remain allocated and subsequent programs are not able to use
them.
Example
var
Handle : Word;
begin
if AllocateExtMem(256, Handle) = 0) then begin
if FreeExtMem(Handle) <> 0
WriteLn('Unable to free XMS');
end
else
WriteLn('Unable to allocate XMS');
First tries to allocate 256K of extended memory and then attempts to free it,
printing error messages if either fails.
See Also
AllocateExtMem
Declaration
function FreeUpperMemBlock(SegmentBase : Word) : Byte;
Purpose
Free an allocated upper memory block.
Description
This function frees a UMB that was allocated by AllocUpperMemBlock. If
SegmentBase does not refer to a valid UMB, an error code $82 is returned.
See Also
AllocUpperMemBlock
Declaration
function GetHandleInfo(XmsHandle : Word; var LockCount, var HandlesLeft : Byte;
var BlockSizeInK : Word) : Byte;
Purpose
Return information about a block associated with an extended memory handle.
Description
This function returns the lock count for this handle, the number of XMS
handles left, and the size in kilobytes of the block associated with this
handle. If you also need the 32 bit linear address of this handle, you must
call LockExtMemBlock.
See Also
AllocateExtMem LockExtMemBlock
Declaration
function GlobalDisableA20 : Byte;
Purpose
Attempt to disable the A20 line.
Description
This function disables 21-bit physical addressing. If you enabled the A20
line, it should be disabled by calling GlobalDisableA20 before exiting your
program.
See Also
GlobalEnableA20 QueryA20
Declaration
function GlobalEnableA20 : Byte;
Purpose
Attempt to enable the A20 line.
Description
This function enables 21-bit physical addressing. It should be used only by
programs that own the HMA. However, since both DOS 5.0 and Windows can make
more efficient use of the HMA than your application, this function is
probably not needed.
See also
GlobalDisableA20 QueryA20
Declaration
function LockExtMemBlock(XmsHandle : Word; var LockedBlock : ExtMemPtr) : Byte;
Purpose
Lock an extended memory block and return its base address as a 32 bit linear
address.
Description
This function locks an extended memory block, thus preventing it from being
moved. XMSHandle must be a valid handle for a previously allocated block of
memory (for example, a handle returned by AllocateExtMem). The LockedBlock
address is valid only while the block is locked. Locked extended memory
blocks should be unlocked as soon as possible. It is not necessary to lock a
block before calling MoveExtMemBlock. A count of the number of locks is
maintained by the XMS memory manager and can be retrieved with the
GetHandleInfo function.
See Also
GetHandleInfo UnlockExtMemBlock
Declaration
function MoveExtMemBlock(BlockLength : LongInt;
SourceHandle : Word; SourcePtr : ExtMemPtr;
DestHandle : Word; DestPtr : ExtMemPtr) : Byte;
Purpose
Move a block of memory.
Description
This function is intended primarily for moving data between extended memory
and conventional memory, however it can also move memory from extended to
extended and conventional to conventional.
BlockLength is the number of bytes to move. It must always be an even number
because MoveExtMemBlock deals in words. Memory areas may overlap only if
SourcePtr is at a lower address than DestPtr. If SourceHandle is 0, then
SourcePtr is interpreted as a normal segment:offset pointer. If SourceHandle
is non-zero, then SourcePtr is interpreted as a 32 bit linear offset into the
block of extended memory associated with SourceHandle. The same is true for
DestHandle and DestPtr. This function does not require that the A20 line be
enabled. It is not necessary to lock extended memory blocks used as SourcePtr
or DestPtr.
Examples
var
Handle : Word;
P, XP : ExtMemPtr;
...
GetMem(P.RealPtr, 32768); {Get 32k}
if (P.RealPtr <> nil) then
if (AllocateExtMem(32, Handle) = 0) then begin
XP.ProtectedPtr := 0;
if MoveExtMemBlock(32768, {32 * 1024 bytes}
0, {No handle - use pointer}
P, {Conventional mem pointer}
Handle, {XMS handle}
XP) <> 0 then {0 offset - start at beginning}
WriteLn('Unable to move block');
end
else
WriteLn('Unable to allocate XMS');
This example attempts to allocate 32K of conventional memory on the heap. If
successful, another 32K block of XMS memory is allocated. If that operation
is successful, data is moved from the conventional block to the XMS block.
Moving from XMS to conventional memory is simply the reverse operation:
XP.ProtectedPtr := 0;
if MoveExtMemBlock(32768, {32 * 1024 bytes}
Handle, {XMS handle}
XP, {0 offset - start at beginning}
0, {No handle - use pointer}
P) <> 0 then {Conventional mem pointer}
WriteLn('Unable to move block');
Moving data from one block to another is also a simple operation:
var
Handle1, Handle2 : Word;
...
if ((AllocateExtMem(256, Handle1) = 0) and
(AllocateExtMem(256, Handle2) = 0)) then begin
XP.ProtectedPtr := 0;
if (MoveExtMemBlock(32768, Handle1, XP, Handle2, XP) <> 0) then
WriteLn('Unable to move block');
end
else
WriteLn('Unable to allocate XMS');
Declaration
function QueryA20 : Byte;
Purpose
Determine if the A20 line is physically enabled.
Description
QueryA20 returns 0 if the A20 line is disabled, 1 if it is enabled, or one of
the codes described in "Error Codes" at the beginning of this section if an
error occurs.
See Also
GlobalDisableA20 GlobalEnableA20
Declaration
function QueryFreeExtMem(var TotalFree, LargestBlock : Word) : Byte;
Purpose
Return total amount of free extended memory and the size of the largest free
block.
Description
This function returns the total amount of free extended memory in TotalFree,
and the size of the largest free block of extended memory in LargestBlock.
Both values are specified in kilobytes.
Example
var
TotalFree, LargestBlock, Handle : Word;
...
QueryFreeExtMem(TotalFree, LargestBlock);
if (LargestBlock >= 1024) then begin
if AllocateExtMem(1024, Handle) <> 0 then
WriteLn('Unable to allocate XMS');
end
else
WriteLn('Cannot allocate as one block');
Checks to see if a 1M block of XMS memory is available, and, if so, allocates
it.
Declaration
function ReleaseHMA : Byte;
Purpose
Release storage in the High Memory Area.
Description
This function releases storage in the HMA that was allocated by RequestHMA.
You must release the HMA before exiting your program.
See Also
RequestHMA
Declaration
function RequestHMA(Bytes : Word) : Byte;
Purpose
Request storage in the High Memory Area.
Description
This function allocates storage in the HMA. Bytes is the minimum amount of
HMA storage needed by the program. If RequestHMA succeeds, the entire HMA is
allocated to the calling program.
Note that since both DOS 5.0 and Windows can use the HMA more effectively
than most application programs, this function is not normally used.
See also
ReleaseHMA
Declaration
function ResizeExtMemBlock(XmsHandle : Word; NewSizeInK : Word) : Byte;
Purpose
Attempt to resize the memory block associated with XMSHandle.
Description
The extended memory block must be unlocked. If NewSizeInK is larger than the
old size, then all data is preserved. If it is smaller, then all data beyond
the end of the new block size is lost.
See Also
AllocateExtMem UnlockExtMemBlock
Declaration
function UnlockExtMemBlock(XmsHandle : Word) : Byte;
Purpose
Unlock an extended memory block.
Description
The 32 bit linear address obtained by calling LockExtMemBlock is invalid
after UnlockExtMemBlock is called.
See Also
LockExtMemBlock
Declaration
function XmsErrorString(ErrorCode : Byte) : String;
Purpose
Return an error string for the specified error code.
Description
This function is passed a valid XMS error code and returns the corresponding
error string. See "Error Codes," above, for a list of the error codes and
associated strings.
Declaration
function XmsInstalled : Boolean;
Purpose
Return True if an XMS memory manager is installed.
Description
This function is used to determine whether an XMS driver is installed.